package com.hb.trade.api.im.hall.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hb.core.pojo.enums.TradeWebsocketMsgEnum;
import com.hb.trade.api.im.main.TradeSystemWebSocketSession;
import com.hb.trade.api.im.main.TradeWebsocketSession;
import com.hb.trade.client.project.BidOpeningClient;
import com.hb.trade.client.project.EvaluationCommitteeClient;
import com.hb.trade.client.project.SectionClient;
import org.apache.commons.lang3.ObjectUtils;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.model.user.layim.LayImUser;
import org.fzzn.core.model.websocket.SocketMessageEntity;
import org.fzzn.core.websocket.handle.MessageHandler;
import org.fzzn.core.websocket.service.ImChatService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.fzzn.core.model.enums.WebsocketMsgEnum.IM;

/**
 * 开标大厅WebSocket消息处理Handler
 *
 * @author Lix1ang
 * @date 2022-1-13 10:13:01
 */
@Service
public class HallMessageHandler extends MessageHandler {

    private static final Logger log = LoggerFactory.getLogger(HallMessageHandler.class);

    private static final SectionClient sectionClient = SpringUtil.getBean(SectionClient.class);
    private static final BidOpeningClient bidOpeningClient = SpringUtil.getBean(BidOpeningClient.class);
    private static final EvaluationCommitteeClient evaluationCommitteeClient = SpringUtil.getBean(EvaluationCommitteeClient.class);

    /**
     * 处理layim即时通讯传过来的消息
     *
     * @param data
     */
    public static void handleIm(Object data) {
        if (data == null) {
            log.warn("handleIm failed for data is null");
            return;
        }

        JSONObject dataContent = JSONUtil.parseObj(data);

        String content = dataContent.getByPath("mine.content", String.class);
        if (StrUtil.isEmpty(content)) {
            log.warn("handleIm failed for content is null, data is [{}]", data);
            return;
        }

        String type = dataContent.getByPath("to.type", String.class);
        log.debug("handleIm msg type is [{}]", type);
        // 这里应该取接收者的头像和ID
        JSONObject from = dataContent.getJSONObject("mine");
        if (from == null) {
            log.warn("handleIm failed for from is null, data is [{}]", data);
            return;
        }
        from.putOpt("sectionId", dataContent.getStr("sectionId"));

        // from对象中的id字段为发送人ID(消息的来源ID（如果是私聊，则是用户id，如果是群聊，则是群组id)
        from.putOpt("content", content);
        from.putOpt("type", type);
        from.putOpt("mine", false);
        from.putOpt("timestamp", DateUtil.current());

        // 发送好友消息
        if ("friend".equals(type)) {
            log.debug("handleIm start ro send friend ,type is  [{}]", type);
            // fromid为消息发送者的ID（比如群组中的某个消息发送者），可用于自动解决浏览器多窗口时的一些问题
            // 在这里默认消息发送者和消息来源是同一个ID
            from.putOpt("fromid", from.getStr("id"));
            // 接收人
            String uname = dataContent.getByPath("to.uname", String.class);
            log.debug("handleIm start ro send friend uname is [{}] ,type is  [{}]", uname, type);
            handleImFriend(from, uname);
        }

        // 发送群聊消息
        if ("group".equals(type)) {
            // fromid为消息发送者的ID（比如群组中的某个消息发送者），可用于自动解决浏览器多窗口时的一些问题
            // 在这里默认消息发送者和消息来源是同一个ID
            from.putOpt("fromid", from.getStr("id"));
            from.putOpt("id", dataContent.getByPath("to.id", String.class));

            // 接收人列表
            JSONArray toList = dataContent.getJSONObject("to").getJSONArray("list");

            if (toList == null) {
                // 正常业务这里size可以是0, 但不应该是null
                toList = JSONUtil.createArray();
            }
            log.debug("handleIm start ro send group toList is [{}] ,type is  [{}]", toList, type);
            Set<String> toUnames = CollUtil.set(false);
            for (Object imUserObj : toList) {
                String uname = JSONUtil.parseObj(imUserObj).getStr("uname");
                toUnames.add(uname);
            }

            handleImGroup(from, toUnames);
        }

    }

    /**
     * 处理好友消息
     *
     * @param from  消息来源对象, 前端传递
     * @param uname 消息接收者标识(即接收消息的人)
     */
    private static void handleImFriend(JSONObject from, String uname) {
        log.debug("handleImFriend start with param uname is [{}]", uname);
        if (StrUtil.isEmpty(uname)) {
            log.warn("Layim: 没有接收人标识, uname is null");
            return;
        }

        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance(from, IM);

        // 查询发送人的标识
        ImChatService recordService = SpringUtil.getBean(ImChatService.class);
        LayImUser layImUser = recordService.getLayimMine(from.getLong("fromid"));
        if (layImUser != null) {
            // 发送人标识赋值
            messageEntity.setFromName(layImUser.getUname());
        }

        // 添加接收人
        messageEntity.add(uname);

        // 发送消息
        log.debug("handleImFriend start to WebSocketSession send messageEntity is [{}]", messageEntity);
        TradeWebsocketSession.send(messageEntity);
    }

    /**
     * 处理群组消息
     *
     * @param from     消息来源对象, 前端传递
     * @param toUnames 消息接收者们的标识集合
     */
    private static void handleImGroup(JSONObject from, Set<String> toUnames) {
        log.debug("handleImGroup start with paran from is [{}], toUname is [{}]", from, toUnames);
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance(from, IM);

        // 查询发送人的标识
        ImChatService recordService = SpringUtil.getBean(ImChatService.class);
        LayImUser layImUser = recordService.getLayimMine(from.getLong("fromid"));
        if (layImUser != null) {
            // 发送人标识赋值
            messageEntity.setFromName(layImUser.getUname());
        }
        // 设置接收人
        messageEntity.setUnames(toUnames);
        // 群组发消息
        log.debug("handleImGroup start to WebSocketSession send messageEntity is [{}]", messageEntity);
        TradeWebsocketSession.send(messageEntity);
    }


    /**
     * 消息发送处理（开标大厅）
     *
     * @param msgType
     * @param msgJSON
     */
    public static void handleHall(Integer msgType, JSONObject msgJSON) {
        //获取消息体中标段Id
        Long sectionId = msgJSON.getLong("sectionId");
        if (null == sectionId) {
            log.warn("WebSocket消息发送失败，标段Id为空");
            return;
        }
        //根据标段Id查询投标人的登录用户名username
/*        Message<List<String>> message = sectionClient.getBidderUserNameBySectionId(sectionId);

        List<String> usernames;
        if (message.isSuccess()) {
            usernames = message.getData();
        } else {
            log.error("未能获取投标人列表信息");
            return;
        }*/

        //根据消息类型获取对应枚举类
        TradeWebsocketMsgEnum websocketMsgEnum = TradeWebsocketMsgEnum.getIns(msgType);

        //构造WebSocket发送消息体
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance();
        messageEntity.setInfoType(websocketMsgEnum.getCode());
        messageEntity.setTypeName(websocketMsgEnum.getShowName());

        JSONObject opt = JSONUtil.createObj()
                .putOpt("status", websocketMsgEnum.getStatus());
        opt.putOpt("sectionId", sectionId);
        messageEntity.setContentData(opt);

        // 设置接收人
/*        for (String username : usernames) {
            messageEntity.add(username);
        }*/

        //执行发送操作
        TradeWebsocketSession.send(messageEntity);
    }

    /**
     * 评标系统发送进入按钮是否显示
     *
     * @param msgType
     * @param msgJSON
     */
    public static void sendSystem(Integer msgType, JSONObject msgJSON) {
        //获取消息体中组长id
        Long headManId = msgJSON.getLong("headManId");
        if (null == headManId) {
            log.warn("WebSocket消息发送失败，标段Id为空");
            return;
        }
        //根据消息类型获取对应枚举类
        TradeWebsocketMsgEnum websocketMsgEnum = TradeWebsocketMsgEnum.getIns(msgType);
        //构造WebSocket发送消息体
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance();
        messageEntity.setInfoType(websocketMsgEnum.getCode());
        messageEntity.setTypeName(websocketMsgEnum.getShowName());
        messageEntity.setContentData(JSONUtil.createObj()
                .putOpt("status", websocketMsgEnum.getStatus())
                .putOpt("sectionId", "test")
                .putOpt("headManId", headManId));

        TradeSystemWebSocketSession.send(messageEntity);
    }

    /**
     * Description: 专家发起二次报价
     *
     * @param msgType 信息类型
     * @param msgJSON 信息内容
     * @author: fengbin
     * @date: 2022/2/24 10:22
     */
    public static void expertSendQuoteMsg(Integer msgType, JSONObject msgJSON) {
        //获取开标标段id
        Long sectionId = msgJSON.getLong("sectionId");
        Integer endType = msgJSON.getInt("endType");
        if (ObjectUtils.isEmpty(sectionId)) {
            log.warn("WebSocket消息发送失败，获取标段id为空");
            return;
        }
        //根据开标标段Id查询该标段下已递交报价的投标人名称
        Message<List<String>> listMessage = bidOpeningClient.lsitBidderNameBySectionId(sectionId);
        if (!listMessage.isSuccess()) {
            log.warn("WebSocket消息发送失败，投标人名称为空");
            return;
        }
        List<String> bidderNames = listMessage.getData();
        log.info("专家发起再次报价供应商接收列表{}", bidderNames);
        //根据消息类型获取对应枚举类
        TradeWebsocketMsgEnum websocketMsgEnum = TradeWebsocketMsgEnum.getIns(msgType);
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance();
        Set<String> names = new HashSet<>();
        bidderNames.forEach(bidderIdName -> {
            names.add(bidderIdName);
        });
        messageEntity.setInfoType(websocketMsgEnum.getCode());
        messageEntity.setTypeName(websocketMsgEnum.getShowName());
        //包装信息
        /*
        openingBidId ： 开标标段id
        endType ：再次报价类型  1：进入下一轮 2：结束报价
         */
        messageEntity.setContentData(JSONUtil.createObj()
                .putOpt("sectionId", sectionId)
                .putOpt("endType", endType)
        );
        messageEntity.setUnames(names);
        TradeSystemWebSocketSession.send(messageEntity);
    }


    /**
     * Description: 供应商二次报价
     *
     * @param msgType 信息类型
     * @param msgJSON 信息内容
     * @author: fengbin
     * @date: 2022/2/24 10:22
     */
    public static void supplierQuoteAgain(Integer msgType, JSONObject msgJSON) {
        Integer offerOrder = msgJSON.getInt("offerOrder");
        Long offerId = msgJSON.getLong("offerId");
        Long sectionId = msgJSON.getLong("sectionId");
        if (ObjectUtils.isEmpty(sectionId)) {
            log.warn("WebSocket消息发送失败，获取标段id为空");
            return;
        }
        //根据标段Id获取专家信息
        // ------------     这里是手机号！！！！      ---------------      //
        Message<List<String>> expertIdCardLists = evaluationCommitteeClient.listExpertIdCardBySectionId(sectionId);
        if (!expertIdCardLists.isSuccess()) {
            log.warn("WebSocket消息发送失败，专家身份证号为空");
            return;
        }
        List<String> expertIdCards = expertIdCardLists.getData();
        log.info("供应商报价专家接收列表{}", expertIdCardLists);
        //根据消息类型获取对应枚举类
        TradeWebsocketMsgEnum websocketMsgEnum = TradeWebsocketMsgEnum.getIns(msgType);
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance();
        Set<String> names = new HashSet<>();
        expertIdCards.forEach(expertIdCard -> {
            names.add(expertIdCard);
        });
        messageEntity.setInfoType(websocketMsgEnum.getCode());
        messageEntity.setTypeName(websocketMsgEnum.getShowName());
        //包装信息
        /*
        openingBidId ： 开标标段id
        offerOrder  :   轮次
        offerId：       投标人id
         */
        messageEntity.setContentData(JSONUtil.createObj()
                .putOpt("sectionId", sectionId)
                .putOpt("offerOrder", offerOrder)
                .putOpt("offerId", offerId)
        );
        messageEntity.setUnames(names);
        TradeSystemWebSocketSession.send(messageEntity);
    }

    /**
     * 开标大厅暂停播放声音
     *
     * @param msgJSON
     */
    public static void stopPlay(JSONObject msgJSON) {
        SocketMessageEntity messageEntity = SocketMessageEntity.getInstance();
        messageEntity.setContentData(msgJSON);
        messageEntity.setTypeName(TradeWebsocketMsgEnum.STOP_PLAY.getShowName());
        messageEntity.setInfoType(TradeWebsocketMsgEnum.STOP_PLAY.getCode());
        TradeSystemWebSocketSession.send(messageEntity);
    }
}
